package engine.BIEngine0_1;

import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.json.JSONException;

import beans.AlgorithmDetail;
import beans.AlgorithmInput;
import beans.AlgorithmOutput;
import beans.AlgorithmParam;
import beans.FullJobState;
import beans.GenerateXmlUriResult;
import beans.HistoryTask;
import beans.HttpConfig;
import beans.HttpResult;
import beans.HttpResultList;
import beans.PhysicalBlockInfor;
import beans.RunningTask;
import beans.SocketLogRecordInfo;
import controller.StartOrderServlet;
import dao.AlgorithmDao;
import dao.HistoryTaskDao;
import dao.JobDao;
import dao.SocketLogDao;
import dao.TaskDao;
import net.CommitJob;
import net.HttpRequest;
import net.sf.json.JSONObject;
import portal.beans.Job;
import portal.cmd.JHCmd;
import portal.common.MyStringUtils;
import portal.dao.ScheduleJobDetailDao;
import portal.engine.JobOperator;
import portal.util.SpringContextUtil;
import utils.FileOper;
import utils.FtpuploadUtil;
import utils.Log4jInit;
import utils.StaticUtil;
import utils.XmlUtil;

public class AlgorithmThread extends Thread implements Serializable {
	private static final long serialVersionUID = 6768353726843187465L;
	private boolean isTerminate;
	public String algorithmHash;
	public TaskThread fatherTask;
	public JSONObject runStateJson;
	public List<FullJobState> fullJobStates;
	public beans.RunnableAlgorithm runnerableAlgorithm;
	public Object controlThreadObject;
	public boolean isPause;
	public boolean isStop;
	private AlgorithmDao algorithmDao;
	private int queryBasicTimes = 0;
	private List<String> runningJobIds;
	public String token;
	private JobDao jobDao;
	private FtpuploadUtil ftpuploadUtil;
	//@Autowired
	private ScheduleJobDetailDao scheduleJobDetailDao ;
	private String applyNode=null;

	/**
	 * 需要修改算法执行文件，防止出现中文名称，并且要统一与之对应的xml文件的名称
	 */
	private String executeAlgorithmFileName;
	/**
	 * inputBlocks:key:input name
	 * 				value:json array of blocks information
	 * value one string eg:{"blk":"c:\\CCJK\\test.bmp_867867","hosts":[{"hostName":"windows22"},{"hostName":"windows35"}]}
	 */
	private Map<String, List<PhysicalBlockInfor>> inputBlocks;
	/**
	 * inputBlocks:key:output name
	 * 				value:json object of one blocks' information
	 */
	private Map<String, List<PhysicalBlockInfor>> outputBlocks;
	
	
//	private static final Logger 	logger = Logger.getLogger(AlgorithmThread.class);
	//static{
	//	logger = Logger.getLogger(AlgorithmThread.class);
	//	PropertyConfigurator.configure("log4j.properties");
	//}
	
	
	
	/**
	 * format date
	 */
	private SimpleDateFormat sf;
	/**
	 * key:job id
	 * value:isCompleted
	 */
	public Map<String,String> jobState;
    /**
     * socket log info
     * key:<subTask hash+algorithm hash>
     * value:socketlogrecordinfo
     */
    private Map<String, SocketLogRecordInfo> socketLogRecordInfos;

    public AlgorithmThread(){
    	
	}
	public AlgorithmThread(TaskThread lineTask, Object controlThreadObject, beans.RunnableAlgorithm runnerableAlgorithm) {
		this();
//		this.algorithmJson = new JSONObject();
		this.fatherTask = lineTask;
		this.runnerableAlgorithm = runnerableAlgorithm;
		this.controlThreadObject = controlThreadObject;
//		this.sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		this.sf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
		this.isTerminate = false;
		this.jobState = new HashMap<>();
		this.fullJobStates = new ArrayList<>();
		this.inputBlocks = new HashMap<>();
		this.outputBlocks = new HashMap<>();
		//this.algorithmDao = new AlgorithmDao();
		this.jobDao = new JobDao();
		this.runningJobIds = new ArrayList<>();
	}
	public AlgorithmThread(TaskThread taskThread, beans.RunnableAlgorithm runnerableAlgorithm) {
		this();
		this.algorithmHash = runnerableAlgorithm.getBlockId();
		this.fatherTask = taskThread;
		this.runnerableAlgorithm = runnerableAlgorithm;
//		this.sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		this.sf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
		this.isPause = false;
		this.isStop = false;
		this.jobState = new HashMap<>();
		this.fullJobStates = new ArrayList<>();
		this.inputBlocks = new HashMap<>();
		this.outputBlocks = new HashMap<>();
		//this.algorithmDao = new AlgorithmDao();
		this.jobDao = new JobDao();
		this.runningJobIds = new ArrayList<>();
	}
	
	// hzj-0624
	public AlgorithmThread(TaskThread taskThread, beans.RunnableAlgorithm runnerableAlgorithm,String applyNode) {
		this(taskThread, runnerableAlgorithm);
		this.applyNode = applyNode;
		
	}

    public Map<String, SocketLogRecordInfo> getSocketLogRecordInfos() {
        return socketLogRecordInfos;
    }

    public void setSocketLogRecordInfos(Map<String, SocketLogRecordInfo> socketLogRecordInfos) {
        this.socketLogRecordInfos = socketLogRecordInfos;
    }

	public List<String> getRunningJobIds() {
		return runningJobIds;
	}

	public void setRunningJobIds(List<String> runningJobIds) {
		this.runningJobIds = runningJobIds;
	}

	@Override
	public void run() {
		super.run();
		this.scheduleJobDetailDao=SpringContextUtil.getBean("scheduleJobDetailDao");
		this.algorithmDao= SpringContextUtil.getBean("algorithmDao");
    	this.ftpuploadUtil=SpringContextUtil.getBean("ftpuploadUtil");
		//2019.1.8修改重启任务时，算法线程并没有启动，导致一些后续的作业更新无法完成
		if(this.isPause)
		{
			this.restartAlgorithm();
		}else{
			this.startAlgorithm();
		}

	}

	public boolean startAlgorithm() {
		/**
		 * 将本算法的各个输入输出从逻辑地址映射到物理地址，如果出现不同输入、不同输出的逻辑地址对应的物理地址块数量不一致，就记录并报错
		 * List里面是每一个block的输入输出信息
		 */
		this.fatherTask.runningTaskBean.runningAlgorithms.put(this.algorithmHash,this);
		try {
		    if (this.fatherTask.runningTaskBean.getModelXmlDir() != null){
                this.insertState("算法开始运行",1);
                this.runningJobIds = this.newStartJobs(this.fatherTask.runningTaskBean.getModelXmlDir());
            }else {
                List<Map<String, PhysicalBlockInfor>> blocks = parseBlocksParams();
                if(blocks==null)return false;
                this.insertState("算法开始运行",blocks.size());
                this.runningJobIds = this.startJobs(blocks);
            }

		} catch (JSONException e) {
			e.printStackTrace();
			return false;
		}
		if(this.runningJobIds==null){
			this.fatherTask.updateState("运行异常");
			return false;

		}
		for(String string:this.runningJobIds){
			if(string.equals("STOP"))
            {
                this.runningJobIds = new ArrayList<>();
                this.jobState.put(string, "STOP");
                doStop();
            }else{
                this.jobState.put(string, "RUNNING");
            }
		}
		int i=0;
		/*try {
			while(!isTerminate){
				i++;
				double a = 40*Math.random();
				int b = (int)(i%a);
				if((HttpConfig.fake)&&b==0){
					this.endOneJob();
				}
				else if(queryBasicTimes<this.runningJobIds.size() * 20){
					if(Thread.currentThread().isInterrupted()){
						break;
					}
					Thread.sleep(1000);
				}
			}
		}
		//如果线程在sleep时，通过interrupt中断线程会抛出错误，因此将错误打印注释掉
		catch (InterruptedException e) {
//			e.printStackTrace();
		}*/
		return true;
	}
	public boolean startNextAlgorithm(){
		this.fatherTask.runningTaskBean.runningAlgorithms.remove(this);
		this.fatherTask.runningTaskBean.completedObjectHash.add(this.algorithmHash);
		if(fatherTask.runningTaskBean.isPause){
			fatherTask.runningTaskBean.restartHashes = this.runnerableAlgorithm.postBlockMap;
			return true;
		}
		if(fatherTask.runningTaskBean.isStop){
			this.fatherTask.updateState("任务名称：" + this.fatherTask.runningTaskBean.getTaskName() + "，停止运行！" );
			this.fatherTask.terminateTask("stopped");
			this.interrupt();
			return true;
		}
		boolean isEnd = false;
		for(Entry<String, Integer> map:this.runnerableAlgorithm.postBlockMap.entrySet()){
			if(map.getKey().contains("uiEnd")){
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				isEnd = true;
			}else if(!this.fatherTask.runningTaskBean.runningAlgorithms.containsKey(map.getKey())){
				this.fatherTask.runningTaskBean.historyDao.recordSubTaskStatement("finish");
				this.fatherTask.startHash(map.getKey(), map.getValue(),false);
			}

		}
		/**
		 * 当前算法的后置有且仅有结束节点
		 */
		if(isEnd && this.runnerableAlgorithm.postBlockMap.size()==1){
			this.fatherTask.terminateTask("finished");
			RunningTask.TASKMAP.removeTask(this.fatherTask.runningTaskBean.getTaskHash());
			this.interrupt();
		}
		return true;
	}



	public boolean doStop() {
		this.fatherTask.runningTaskBean.runningAlgorithms.remove(this);
		this.fatherTask.updateState("算法运行被终止！");
		boolean result = this.algorithmDao.algorithmFinishedStopPauseStateUpdate(4,this.runningJobIds,this.fatherTask.runningTaskBean.getTaskHash(),this.runnerableAlgorithm.getBlockId());
		this.interrupt();
		return result;
	}

	public boolean doRestart() {
		//2018-7-22修改
		this.fatherTask.updateState("算法恢复运行！");
		return this.algorithmDao.algorithmFinishedStopPauseStateUpdate(2,this.runningJobIds,this.fatherTask.runningTaskBean.getTaskHash(),this.runnerableAlgorithm.getBlockId());
	}


	public boolean doPause() {
//		boolean result = false;
//		this.fatherTask.updateState("算法名称："+this.runnerableAlgorithm.getAlgorithmName()+"，运行被暂停！");
//		synchronized (this.fatherTask.runningTaskBean.controlThreadObject) {
//			try {
//				/**
//				 * pause at here once line :
//				 * 'this.notifyAlltest.ojb.notifyAll()' is executed
//				 * the following line will be execute
//				 */
//				this.fatherTask.runningTaskBean.controlThreadObject.wait();
//				result = true;
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//		}
//		return result;
		//2018-7-22修改
		this.fatherTask.runningTaskBean.runningAlgorithms.remove(this);
		this.fatherTask.updateState("算法运行被暂停！");
		boolean result = this.algorithmDao.algorithmFinishedStopPauseStateUpdate(3,this.runningJobIds,this.fatherTask.runningTaskBean.getTaskHash(),this.runnerableAlgorithm.getBlockId());
		this.interrupt();
		return result;
	}

	private void endOneJob() {
		if(runningJobIds.size()>0){
			String param = "taskId="+this.fatherTask.runningTaskBean.getTaskHash()+"&algorithmId="+this.runnerableAlgorithm.getBlockId()+
					"&jobId="+runningJobIds.get(0)+"&status=0";
			this.fatherTask.updateState("作业完成，ID为"+runningJobIds.get(0));
//			Log4jInit.logger.info(param);
			JSONObject result = JSONObject.fromObject(HttpRequest.sendPost("http://localhost:8080/JCPT/ws/task/callback", param));
			this.runningJobIds.remove(0);
			if(runningJobIds.size()==0){
				isTerminate =true;
			}
		}else{
			isTerminate =true;
		}
	}

	
	private List<String> startJobs(List<Map<String, PhysicalBlockInfor>> blocksParams) throws JSONException {
		List<String> jobIds = new ArrayList<>();
		List<String> fileList = new ArrayList<>();  //输入文件list

		 String jh_files = "";
	       // HttpConfig.gpuType,
	       String gpuType = "";
	       // HttpConfig.execNode,
	       String execNode = "";
	       
		/**
		 * 从服务器获取token
		 */
		HttpResult tokenResult = AlgorithmOperator.getToken(HttpConfig.userName, HttpConfig.passWord);
		if(tokenResult.isResult()){
			this.token = tokenResult.getMessage();
			this.fatherTask.updateState("完成token获取");
		}else{
			this.fatherTask.updateState("token获取失败，服务器原因:" + tokenResult.getMessage());
			return null;
		}
		Log4jInit.logger.info("====AlthorithmThread:startJobs====");
		

		/**
		 * 上传算法执行文件
		 * 拼接上传文件后，服务器端的地址 由http.roperties里面的ftpAlgorithmFileUri + <task id>/<algorithm id>/file name
		 */
		executeAlgorithmFileName = UUID.randomUUID().toString().substring(10);
		String algorithmId = this.runnerableAlgorithm.getAlgorithmDetail().getId()+"";
		//先去父任务中找到算法id对应的ftp文件路径
	List<String> list = this.fatherTask.runningTaskBean.getAlgorithmIdAndFtpUri(algorithmId);
		String algorithmFileName = this.runnerableAlgorithm.getAlgorithmDetail().getLocationUri();
		algorithmFileName = algorithmFileName.substring(algorithmFileName.lastIndexOf("/")+1);
		algorithmFileName = HttpConfig.ftpAlgorithmUri+this.fatherTask.runningTaskBean.getTaskId()+"/"
				+this.runnerableAlgorithm.getAlgorithmDetail().getId()+"/"+algorithmFileName;
	
		
		
		//若FTPURI存在，则无需上传
		/*if(list.size()!=0){
			this.fatherTask.updateState("完成算法执行文件上传");
		}else{
			this.fatherTask.updateState("算法执行文件上传失败"+algorithmFileName);
			Log4jInit.logger.info("算法执行文件上传失败:"+algorithmFileName);
			return null;
		}*/
		
		String ftpIniFileUri=analysisIniUri(list,this.fatherTask.runningTaskBean.getTaskHash());


		/**
		 * 上传每一个block，并且启动对应的job
		 */

		for(int m=0;m<blocksParams.size();m++){
			XmlUtil xmlUtil = new XmlUtil();
			Map<String,PhysicalBlockInfor> oneBlock = blocksParams.get(m);
			GenerateXmlUriResult paramXmlUriResult = generateParamsXml(xmlUtil,executeAlgorithmFileName, oneBlock, "block"+m+"_");
			/**
			 * 上传该job对应的xml文件
			 * 拼接上传文件后，服务器端的地址 由http.roperties里面的ftpAlgorithmFileUri + <task id>/<algorithm id>/file name
			 */
			//paramXmlFileUri：是本地生成的带有uuid唯一标识的xml文件的绝对路径
			//paramFileName：是算法文件名.xml
			String paramXmlFileUri = paramXmlUriResult.getParamsXmlFilePathUriWithUUID();
			String paramFileName = paramXmlUriResult.getParamsXmlFilePathUri();
			Log4jInit.logger.info("paramXmlFileUri:"+paramXmlFileUri);
//			 Log4jInit.logger.info("paramFileName:"+paramFileName);
			//2018-8-7在上传的xml文件上面一层加一个uuid的文件夹
			paramFileName = HttpConfig.ftpParamsUri+this.fatherTask.runningTaskBean.getTaskId()+"/"
					+this.runnerableAlgorithm.getAlgorithmDetail().getId()+"/"
					+UUID.randomUUID().toString().substring(0,5)+"/"+paramFileName;
			Log4jInit.logger.info("ftp paramFileName:"+paramFileName);
			
			/**
    		 *根据输入文件，查询文件分块的位置，并获取节点位置的排序，指定调度任务所在节点，输入所有输入文件的位置List<String>
    		 *先将MDL文件转换为实际路径
    		 *只有实际算法需要此步骤，辅助算法不需要
    		 */
		
    	String taskPath = paramXmlFileUri;
    		int functionId = this.runnerableAlgorithm.getAlgorithmDetail().getFunction().getCategoryId();
    		Log4jInit.logger.info("fileSystemIP:"+HttpConfig.fileSystemIP);
    		if((!HttpConfig.fileSystemIP.equals(""))){   // fileSystemIP不为空时，判断文件位置
    		    
    			if((!this.runnerableAlgorithm.getAlgorithmDetail().isGenetic())){

    				if(functionId!=3 && functionId!=0){  //在数据库中，category类型为3的是辅助算法
    							Log4jInit.logger.info("functionId :"+functionId);
    		     	    Log4jInit.logger.info("TaskMdlPathParse taskPath :"+taskPath);
    		     	    fileList = SchedByLocation.getMdlRealPath(taskPath,true,HttpConfig.useCacheDisk);
    		     	    if(fileList != null){
    		     	    	execNode = SchedByLocation.getFileLocations(fileList,false);
    		     	    }
    		         }
    		    // StaticUtil.deleteFile(taskPath);  //删除接收的task文件
    			}
    		     
    		}else{
    			if((!this.runnerableAlgorithm.getAlgorithmDetail().isGenetic())){
    				fileList = SchedByLocation.getMdlRealPath(taskPath,false,false); //在xml拼装时已判断	
    			}
    			
    		}
    		
    		/**
    		* 创建一个bat文件，在调度节点创建输出盘的目录
    		*/
    		if(HttpConfig.useCacheDisk){
    		String dirBat =	SchedByLocation.createMkdirBat(taskPath);
    		jh_files = jh_files +" " + dirBat;
    		Log4jInit.logger.info("jh_files dir::"+jh_files);
    		}
			
            String upXmlResult = null;
            try {
//            	upXmlResult = ftpuploadUtil.uploadFile(paramXmlFileUri,paramFileName);
            if(HttpConfig.copyFile){
            		upXmlResult = ftpuploadUtil.uploadFileByCopy(paramXmlFileUri,paramFileName);
            	}else{
            		upXmlResult = ftpuploadUtil.uploadFile(paramXmlFileUri,paramFileName);
            			} 
                
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(upXmlResult!=null && upXmlResult!="" && upXmlResult!="undefined"){
				this.fatherTask.updateState("完成分块："+(m+1)+"的参数XML文件上传");
			//	StaticUtil.deleteFile(paramXmlFileUri);
			}else{
				this.fatherTask.updateState("分块："+(m+1)+"的参数XML文件上传失败");
				return null;
			}
            
       
			/**
			 * 提交并启动一个job
			 */
			String nodeGroup = this.runnerableAlgorithm.getAlgorithmDetail().getPlatform();
//			nodeGroup = (nodeGroup.equals("windows"))?"Windows":"Linux";
			nodeGroup = "";
			String mem = this.runnerableAlgorithm.getAlgorithmDetail().getMinRamRemaining()+"";
			mem = mem.replaceAll(".0","");
			String resource = "ut>"+ this.runnerableAlgorithm.getAlgorithmDetail().getMinCpuIdle() +"&&mem>"+ mem;
	//		String jh_files = "";
			String ftpFilePath = "";
			for(int rf=0;rf<list.size();rf++){
				jh_files = jh_files+" "+list.get(rf);
				ftpFilePath = list.get(rf);
			}

			jh_files = jh_files +" " + paramFileName;
			//jh_files = jh_files +" " + ftpIniFileUri;
		
			//a.zip---a.exe 直接取a.exe，不需要完整路径
		/*	String exe = HttpConfig.ftpAlgorithmUri+this.fatherTask.getTaskId()+"/"+this.runnerableAlgorithm.getAlgorithmDetail().getId()+"/";
			algorithmFileName = algorithmFileName.substring(algorithmFileName.lastIndexOf("/")+1);
			algorithmFileName = exe + algorithmFileName.substring(0, algorithmFileName.lastIndexOf("."));
			algorithmFileName = algorithmFileName+".exe";*/
			algorithmFileName = algorithmFileName.substring(algorithmFileName.lastIndexOf("/")+1, algorithmFileName.lastIndexOf("."));
			algorithmFileName = algorithmFileName+runnerableAlgorithm.getAlgorithmDetail().getPostfix();

		
			String paramFileNameCommand = paramFileName.substring(paramFileName.lastIndexOf("/")+1);
			String cmd = algorithmFileName;
			
			//下面三行是把执行文件的中文名称替换的代码
//			algorithmFileName = executeAlgorithmFileName+runnerableAlgorithm.getAlgorithmDetail().getPostfix();
//
//			String paramFileNameCommand = paramFileName.substring(paramFileName.lastIndexOf("/")+1);
//			String cmd = algorithmFileName;
			 String tm = algorithmFileName.substring(0, cmd.lastIndexOf("."));
			String cpuNum = "";
			if(this.runnerableAlgorithm.getAlgorithmDetail().isUseMpi()){
				//如果是MPI算法

				cpuNum = this.runnerableAlgorithm.getAlgorithmDetail().getCpuNum();

//				org.json.JSONObject params = xmlUtil.parseXMLFiletoJson(new File(paramXmlFileUri));


				if(cpuNum!=null && cpuNum!="" && cpuNum!="undefined"){
					cmd = "mpiexec -n "+ cpuNum +" "+tm+"\\"+tm+"\\"+ algorithmFileName;
	//				cmd = "mpiexec -n "+ cpuNum +" "+ algorithmFileName;
				}else{

				cmd = tm+"\\"+tm+"\\"+ algorithmFileName;
			//		cmd =  algorithmFileName;
				}

			}else{
				//非MPI算法
				
				if(this.runnerableAlgorithm.getAlgorithmDetail().isGenetic()){
					/**
					 * 如果是遗留算法
					 */
					cmd = tm+"\\"+tm+"\\"+cmd + " ";
				
					//2018-7-26注释，将input、output、params都改为从生成xml文件的返回值中获取，不再去xml文件中解析了
//					org.json.JSONObject params = xmlUtil.parseXMLFiletoJson(new File(paramXmlFileUri));
//					Map<String,String> inputMap = xmlUtil.parseInputValue(params);
//					Map<String,String> outputMap = xmlUtil.parseOutputValue(params);
//					Map<String,String> paramMap = xmlUtil.parseParamValue(params);
					Map<String,String> inputMap = paramXmlUriResult.getInputMap();
					Map<String,String> outputMap = paramXmlUriResult.getOutputMap();
					Map<String,String> paramMap = paramXmlUriResult.getParamMap();
					for(AlgorithmInput input:this.runnerableAlgorithm.getAlgorithmDetail().getAlgorithmInputs()){
//					Log4jInit.logger.info("input default:"+input.getNameDefault());
						if(input.getNameDefault()){
							cmd += inputMap.get(input.getInputName()) + " ";
						}else{
							cmd += input.getInputName() + " " + inputMap.get(input.getInputName()) + " ";
						}
						fileList.add(inputMap.get(input.getInputName()));
					}
					for(AlgorithmOutput output:this.runnerableAlgorithm.getAlgorithmDetail().getAlgorithmOutputs()){
//					Log4jInit.logger.info("output default:"+output.getNameDefault());

						if(output.getNameDefault()){
							cmd += outputMap.get(output.getOutputName()) + " ";
						}else{
							cmd += output.getOutputName() + " " + outputMap.get(output.getOutputName()) + " ";
						}
					}
					if(paramMap!=null){
						for(AlgorithmParam param:this.runnerableAlgorithm.getAlgorithmDetail().getAlgorithmParams()){
//					Log4jInit.logger.info("param default:"+param.getNameDefault());

							if(param.getNameDefault()){
								cmd += paramMap.get(param.getParamSymbol()) + " ";
							}else{
								cmd += param.getParamSymbol() + " " + paramMap.get(param.getParamSymbol()) + " ";
							}
						}
					}
				}else{
				cmd = tm+"\\"+tm+"\\"+cmd + " " + paramFileNameCommand;
				//	cmd = cmd + " " + paramFileNameCommand;
				}
			}
			 Log4jInit.logger.info("cmd:"+cmd);
			 Log4jInit.logger.info("jh_files:"+jh_files);
//			String remoteFileLoc = "";
			
		     /**
             *根据输入文件，查询文件分块的位置，并获取节点位置的排序，指定调度任务所在节点
             */
			if((!HttpConfig.fileSystemIP.equals(""))&& this.runnerableAlgorithm.getAlgorithmDetail().isGenetic()){
				execNode = SchedByLocation.getFileLocations(fileList,true);
			}
			
			
//			Log4jInit.logger.info("parallel strategy:"+this.runnerableAlgorithm.getParallelStrategy());
//			Log4jInit.logger.info("priority:"+this.runnerableAlgorithm.getPriority());
			//paramXmlUriResult.getExecNodes()  --windows33
			
		
			CommitJob commitJob = new CommitJob(token, cmd,
					this.fatherTask.runningTaskBean.getTaskHash(), this.runnerableAlgorithm.getBlockId(), HttpConfig.userName,
					this.runnerableAlgorithm.getAlgorithmDetail().getPlatform(),this.runnerableAlgorithm.getPriority(),
					HttpConfig.gpuType, this.runnerableAlgorithm.getAlgorithmDetail().isContainGpu(),resource,
					execNode, this.runnerableAlgorithm.getAlgorithmDetail().isUseMpi(),
					this.runnerableAlgorithm.getHostGroup(),this.runnerableAlgorithm.getParallelStrategy(),jh_files,cpuNum);


			commitJob.setFtpAlgorithmUri(algorithmFileName);
			commitJob.setFtpParamsXmlUri(paramFileName);
			HttpResult startResult = null;
			if(!fatherTask.runningTaskBean.isStop){
				 startResult = AlgorithmOperator.startJob(commitJob);
				
			}
			if(startResult == null)
			{
				this.fatherTask.updateState("第"+(m+1)+"个作业被终止");
                jobIds.add("STOP");
			}else{
				if(startResult.isResult()){
					jobIds.add(startResult.getMessage());

					//作业启动成功后，获取作业详情数据
					HttpResultList result = null;
					try {
						result = AlgorithmOperator.getJobFullState(startResult.getMessage(), token);
					} catch (IOException e) {
						e.printStackTrace();
					}
					FullJobState fullJobState = (FullJobState)result.getDatas().get(0);
					String executionHost = fullJobState.getExecutionHost().split("]")[0].replaceAll("[\"\\[]", "");
					//同步调度的作业表
					if(HttpConfig.synchronize){
						ftpFilePath = ftpFilePath.substring(0,ftpFilePath.lastIndexOf("/")+1);
						Job job = new Job();
						job.setJobId(startResult.getMessage());
						job.setName(fullJobState.getJobName());
						job.setJobQueue(fullJobState.getQueue());
						job.setJobPriority(fullJobState.getPriority());
						job.setStrategy(this.runnerableAlgorithm.getParallelStrategy());
						job.setCommand(fullJobState.getCommand());
						job.setMemoryUsage(fullJobState.getMemUsage());
						if(!cpuNum.equals("")){
							job.setCPUkernelNumber(cpuNum);
							job.setMPINumber(cpuNum);
						}
						//获取算法文件本地uri
						//AlgorithmDao algorithmDao = new AlgorithmDao();
						AlgorithmDetail algorithmDetail = algorithmDao.getAlgorithmDetail(algorithmId, null);
						job.setDependentFiles(algorithmDetail.getLocationUri());
						scheduleJobDetailDao.insertScheduleJobDetail(commitJob,job,"RUNNING",ftpFilePath,
								"1",executionHost,fullJobState.getCpuUsage());

					}
					//2019-1-3, 添加作业名称和作业全部详情两个字段
					jobDao.insertJobState(commitJob,this.fatherTask.runningTaskBean.getTaskHash(),
							this.runnerableAlgorithm.getBlockId(),startResult.getMessage(),
							this.runnerableAlgorithm.getAlgorithmDetail().getId()+"",(m+1)+"",
							fullJobState.getJobName(),JSONObject.fromObject(fullJobState).toString());
				/*jobDao.insertJobState(commitJob,this.fatherTask.runningTaskBean.getBatchTaskHash(),
						this.runnerableAlgorithm.getBlockId(),startResult.getMessage(),
						this.runnerableAlgorithm.getAlgorithmDetail().getId()+"",(m+1)+"");*/
					this.fatherTask.updateState("启动作业，ID为："+startResult.getMessage());
					//2018-7-14 将任务启动之后，需要及时将相关的日志信息记录到数据库中去
					String key = fatherTask.runningTaskBean.getTaskHash()+this.runnerableAlgorithm.getBlockId();
					SocketLogRecordInfo socketLogRecordInfo = this.getSocketLogRecordInfos().get(key);
					String psn = socketLogRecordInfo.getPsn();
					String id = socketLogRecordInfo.getId();
					String jobId = startResult.getMessage();
					new SocketLogDao().insertAlgorithmState(HttpConfig.socketLogLevel,2+"",psn,id,jobId);
				}else{
					this.fatherTask.updateState("算法提交启动失败，服务器原因："+startResult.getMessage());
				}
			}
		}
		return (jobIds.size()==blocksParams.size())?jobIds:null;

	}
	
	private boolean checkToken(){
		 /**
         * 从服务器获取token
         */
        HttpResult tokenResult = AlgorithmOperator.getToken(HttpConfig.userName, HttpConfig.passWord);
        if(tokenResult.isResult()){
            this.token = tokenResult.getMessage();
            this.fatherTask.updateState("完成token获取");
        }else{
            this.fatherTask.updateState("token获取失败，服务器原因:" + tokenResult.getMessage());
            return false;
        }
        return true;
	}
    /**
     * paramXmlFileUri：是本地xml文件的绝对路径
     */
    private List<String> newStartJobs(String paramXmlFileUri) throws JSONException {

        List<String> jobIds = new ArrayList<>();
        List<String> fileList = new ArrayList<>();
       if(checkToken()==false)
    	   return null;
       
       String jh_files = "";
       // HttpConfig.gpuType,
       String gpuType = "";
       // HttpConfig.execNode,
       String execNode = "";
       
       /**
        *根据输入文件，查询文件分块的位置，并获取节点位置的排序，指定调度任务所在节点，输入所有输入文件的位置List<String>
        *先将MDL文件转换为实际路径
        *只有实际算法需要此步骤，辅助算法不需要
        */
       String taskPath = this.fatherTask.runningTaskBean.getModelXmlDir();
   	int functionId = this.runnerableAlgorithm.getAlgorithmDetail().getFunction().getCategoryId();
   	
	// hzj-0624：this.applyNode 若不为空，优先使用本节点
   if(MyStringUtils.isNotEmpty(this.applyNode)){
	   Log4jInit.logger.info("===============applyNode exists=============");
	   execNode = this.applyNode;
   }else if(MyStringUtils.isNotEmpty(HttpConfig.fileSystemIP)){   // fileSystemIP不为空时，判断文件位置
	       
	        if(functionId!=3 && functionId!=0){  //在数据库中，category类型为3的是辅助算法
	        	    Log4jInit.logger.info("TaskMdlPathParse taskPath :"+taskPath);
	        	    fileList = SchedByLocation.getMdlRealPath(taskPath,true,HttpConfig.useCacheDisk);
	        	    if(fileList != null){
	        	    	execNode = SchedByLocation.getFileLocations(fileList,false);
	        	    }
	            }
//	        StaticUtil.deleteFile(taskPath);  //删除接收的task文件
       }else{
//       	fileList = SchedByLocation.getMdlRealPath(taskPath,false,HttpConfig.useCacheDisk);
       }
   
   /**
    * 创建一个bat文件，在调度节点创建输出盘的目录
    */
   if(HttpConfig.useCacheDisk){
   String dirBat =	SchedByLocation.createMkdirBat(taskPath);
   jh_files = jh_files + dirBat +" ";
  	//	jh_files = jh_files +" " + ftpIniFileUri;
   Log4jInit.logger.info("jh_files dir::"+jh_files);
   }
   
        /**
         * 上传算法执行文件
         * 拼接上传文件后，服务器端的地址 由http.roperties里面的ftpAlgorithmFileUri + <task id>/<algorithm id>/file name
         */
        executeAlgorithmFileName = UUID.randomUUID().toString().substring(10);
        String algorithmId = this.runnerableAlgorithm.getAlgorithmDetail().getId()+"";
        //先去父任务中找到算法id对应的ftp文件路径
        List<String> list = this.fatherTask.runningTaskBean.getAlgorithmIdAndFtpUri(algorithmId);
     	Log4jInit.logger.info("====AlthorithmThread:newStartJobs====");
       
        /**
         * 上传ini文件
         */
     	String ftpIniFileUri=analysisIniUri(list,this.fatherTask.runningTaskBean.getTaskHash());
        if(null==ftpIniFileUri)return null;;
        /**
         * 获取分组信息
         */
//        HttpResult groupResult = AlgorithmOperator.getHostGroupList(token);
//        String groupNode = null;
       /* if(groupResult.isResult()){
            groupNode = groupResult.getMessage();
            this.fatherTask.updateState("完成分组信息获取");
        }else{
            this.fatherTask.updateState("获取分组信息失败，服务器原因："+groupResult.getMessage());
        }*/

        /**
         * 上传每一个block，并且启动对应的job
         * 上传该job对应的xml文件
         * 拼接上传文件后，服务器端的地址 由http.roperties里面的ftpAlgorithmFileUri + <task id>/<algorithm id>/file name
         */
        String ftpFileUri ="";
        if(MyStringUtils.isNotEmpty(taskPath)){
        	 ftpFileUri = uploadJobXML(taskPath);
             if(ftpFileUri==null)
             	return null;
        }
       
        /**
         * 提交并启动一个job
         */
        String nodeGroup = this.runnerableAlgorithm.getAlgorithmDetail().getPlatform();
//			nodeGroup = (nodeGroup.equals("windows"))?"Windows":"Linux";
        nodeGroup = "";
        String mem = this.runnerableAlgorithm.getAlgorithmDetail().getMinRamRemaining()+"";
        mem = mem.replaceAll(".0","");
        String resource = "ut>"+ this.runnerableAlgorithm.getAlgorithmDetail().getMinCpuIdle() +"&&mem>"+ mem;
        resource = "";
        
		String ftpFilePath = "";
        for(int rf=0;rf<list.size();rf++){
            jh_files = jh_files+list.get(rf)+" ";
			ftpFilePath = list.get(rf);
        }

        jh_files = jh_files + ftpFileUri;
	//	jh_files = jh_files +" " + ftpIniFileUri;
        Log4jInit.logger.info("jh_files::"+jh_files);
        
        String algorithmFileName = spellAlgorithmName();

        String tm = algorithmFileName.substring(0, algorithmFileName.lastIndexOf("."));        
        
        JSONObject json=JSONObject.fromObject(FileOper.readTaskJson(this.fatherTask.runningTaskBean.getJson()));
        JSONObject jOther=json.getJSONArray("other").getJSONObject(0).getJSONObject("json");
			Boolean isMpi= null; //Other.getBoolean("isMpi");
			Integer MPI= null; //jOther.getInt("MPI");
			String host=null; //jOther.getString("host");
//			String applyNode = null;  //接口传入执行节点
			
        if((!jOther.isEmpty()) && (!jOther.isNullObject())){
        	
        	if(jOther.containsKey("isMpi")){
        		isMpi = jOther.getBoolean("isMpi");
        	}
        	if(jOther.containsKey("MPI")){
        		MPI = jOther.getInt("MPI");
        	}
        	if(jOther.containsKey("host")){
        		host = jOther.getString("host");
        	}
        	
          }

        String cpuNum = "",cmd=algorithmFileName;
        
        if(this.runnerableAlgorithm.getAlgorithmDetail().isUseMpi()){
            //如果是MPI算法
        	Log4jInit.logger.info("AT  getCpuNum::"+this.runnerableAlgorithm.getAlgorithmDetail().getCpuNum());
            cpuNum = this.runnerableAlgorithm.getAlgorithmDetail().getCpuNum();
            if(MPI!=null&&MPI!=0){
            	cpuNum=MPI.toString();
            
            }
        	
          	//cpuNum应为正整数
        	if(cpuNum.equals("0")){
        		cpuNum = "1";
        	}
        	Log4jInit.logger.info("AT trans cpuNum::"+cpuNum);
            cmd = genMPICmd(algorithmFileName, cpuNum, tm);
        }else{
            //非MPI算法
            if(this.runnerableAlgorithm.getAlgorithmDetail().isGenetic()){
                cmd = genLegacyAlgorithmCmd(cmd, tm);
            }else{
            	String paramFileNameCommand = ftpFileUri.substring(ftpFileUri.lastIndexOf("/")+1);
                cmd =tm+"\\"+tm+"\\"+ cmd + " " + paramFileNameCommand;
           // 	 cmd = cmd + " " + paramFileNameCommand;
            }
        }
        Log4jInit.logger.info("cmd:"+cmd);
      
         
        
    
        CommitJob commitJob = collectCommitJob(ftpFileUri, nodeGroup, resource, jh_files, algorithmFileName, cpuNum,cmd, gpuType, execNode);
        HttpResult startResult = null;
        if(!fatherTask.runningTaskBean.isStop){
            startResult = AlgorithmOperator.startJob(commitJob);
        }
        if(startResult == null)
        {
            this.fatherTask.updateState("第"+(1)+"个作业被终止");
            jobIds.add("STOP");
        }else{
            if(startResult.isResult()){//算法提交成功，则将相关信息记录到数据库
                jobIds.add(startResult.getMessage());
					saveJobToDb(algorithmId, ftpFilePath, cpuNum, commitJob, startResult);
            }else{
                this.fatherTask.updateState("算法提交启动失败，服务器原因："+startResult.getMessage());
            }
        }
        return jobIds;
    }
	/**
	 * @param ftpFileUri
	 * @param nodeGroup
	 * @param resource
	 * @param jh_files
	 * @param algorithmFileName
	 * @param cpuNum
	 * @param cmd
	 * @param gpuType
	 * @param execNode
	 * @return
	 */
	private CommitJob collectCommitJob(String ftpFileUri, String nodeGroup, String resource, String jh_files,
			String algorithmFileName, String cpuNum, String cmd, String gpuType, String execNode) {
		
		//hzj-0624:优先选择applyNode的节点
		String exec = MyStringUtils.isNotEmpty(this.applyNode)?this.applyNode:execNode;
		CommitJob commitJob = new CommitJob(token,
                cmd,
                this.fatherTask.runningTaskBean.getTaskHash(),
                this.runnerableAlgorithm.getBlockId(),
                HttpConfig.userName,
                this.runnerableAlgorithm.getAlgorithmDetail().getPlatform(),
                this.runnerableAlgorithm.getPriority(),	
                gpuType,
                this.runnerableAlgorithm.getAlgorithmDetail().isContainGpu(),
                resource,
                exec,///调度执行具体节点
                this.runnerableAlgorithm.getAlgorithmDetail().isUseMpi(),
                nodeGroup,
                this.runnerableAlgorithm.getParallelStrategy(),
                jh_files,
                cpuNum);

        commitJob.setFtpAlgorithmUri(algorithmFileName);
        commitJob.setFtpParamsXmlUri(ftpFileUri);
		return commitJob;
	}
	/**
	 * @param algorithmId
	 * @param ftpFilePath
	 * @param cpuNum
	 * @param commitJob
	 * @param startResult
	 */
	private void saveJobToDb(String algorithmId, String ftpFilePath, String cpuNum, CommitJob commitJob,
			HttpResult startResult) {
		//作业启动成功后，获取作业详情数据
		HttpResultList result = null;
		try {
			result = AlgorithmOperator.getJobFullState(startResult.getMessage(), token);
		} catch (IOException e) {
			e.printStackTrace();
		}
		FullJobState fullJobState = (FullJobState)result.getDatas().get(0);
		String executionHost = fullJobState.getExecutionHost().split("]")[0].replaceAll("[\"\\[]", "");
		//同步调度的作业表
		if(HttpConfig.synchronize){
			//ScheduleJobDetailDao scheduleJobDetailDao = new ScheduleJobDetailDao();
			ftpFilePath = ftpFilePath.substring(0,ftpFilePath.lastIndexOf("/")+1);
			Job job = new Job();
			job.setJobId(startResult.getMessage());
			job.setName(fullJobState.getJobName());
			job.setJobQueue(fullJobState.getQueue());
			job.setJobPriority(fullJobState.getPriority());
			job.setStrategy(this.runnerableAlgorithm.getParallelStrategy());
			job.setCommand(fullJobState.getCommand());
			job.setMemoryUsage(fullJobState.getMemUsage());
			if(!cpuNum.equals("")){
				job.setCPUkernelNumber(cpuNum);
				job.setMPINumber(cpuNum);
			}
			//获取算法文件本地uri
			//AlgorithmDao algorithmDao = new AlgorithmDao();
			AlgorithmDetail algorithmDetail = algorithmDao.getAlgorithmDetail(algorithmId, null);
			job.setDependentFiles(algorithmDetail.getLocationUri());
			scheduleJobDetailDao.insertScheduleJobDetail(commitJob,job,"RUNNING",ftpFilePath,
					"1",executionHost,fullJobState.getCpuUsage());

		}
		closeHostForExclusiveModelId(this.fatherTask.runningTaskBean.getBatchTaskHash(),startResult.getMessage());
		jobDao.insertJobState(commitJob,this.fatherTask.runningTaskBean.getTaskHash(),
		        this.runnerableAlgorithm.getBlockId(),startResult.getMessage(),
		        this.runnerableAlgorithm.getAlgorithmDetail().getId()+"",(1)+"",
				fullJobState.getJobName(),JSONObject.fromObject(fullJobState).toString());
		this.fatherTask.updateState("启动作业，ID为："+startResult.getMessage());
		//2018-7-14 将任务启动之后，需要及时将相关的日志信息记录到数据库中去
		String key = fatherTask.runningTaskBean.getTaskHash()+this.runnerableAlgorithm.getBlockId();
		SocketLogRecordInfo socketLogRecordInfo = this.getSocketLogRecordInfos().get(key);
		String psn = socketLogRecordInfo.getPsn();
		String id = socketLogRecordInfo.getId();
		String jobId = startResult.getMessage();
		new SocketLogDao().insertAlgorithmState(HttpConfig.socketLogLevel,2+"",psn,id,jobId);
	}
	private  void closeHostForExclusiveModelId(String taskHash,String jobId){
		HistoryTaskDao td =new HistoryTaskDao();
		HistoryTask ht =td.getHistoryTaskByTaskHash(taskHash);
		//JSONObject json =new JSONObject();
		if(StartOrderServlet.isExclusiveModelIdAndJust(""+ht.getModel_id())){
			pendJobId(ht.getModel_id(),jobId);
			try {
				String status ="PEND";
				FullJobState fullJobState=null;
				while("PEND".equals(status)){
					HttpResultList httpResultList= JobOperator.getScheduleJobFullState(jobId, JobOperator.getToken(HttpConfig.userName, HttpConfig.passWord).getMessage());
					fullJobState = (FullJobState) httpResultList.getDatas().get(0);
					status=fullJobState.getStatus();
					try {
						TimeUnit.SECONDS.sleep(8);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
				if(status.contains("RUN")&&fullJobState!=null){
					JHCmd  j=new JHCmd();
					boolean b =j.hostClose(fullJobState.getExecutionHost().split("]")[0].replaceAll("[\"\\[]", ""));
					Log4jInit.logger.info("********hostClose:"+b);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//td.getTaskThread(taskHash)
	}
	private static synchronized void pendJobId(int modelId,String jobId){
			pendJobId(""+modelId,jobId);
	}
	private static synchronized void pendJobId(String modelId,String jobId){
		String fileName =HttpConfig.taskJsonFileUri+modelId+"_exclusiveNode.json";
		FileOper.writeFile(fileName,FileOper.readFile(fileName)+ jobId+"#");
	}
	/**
	 * @return
	 */
	private String spellAlgorithmName() {
		String algorithmFileName = this.runnerableAlgorithm.getAlgorithmDetail().getLocationUri();
        algorithmFileName = algorithmFileName.substring(algorithmFileName.lastIndexOf("/")+1);
        algorithmFileName = HttpConfig.ftpAlgorithmUri+this.fatherTask.runningTaskBean.getTaskId()+"/"
                +this.runnerableAlgorithm.getAlgorithmDetail().getId()+"/"+algorithmFileName;
        algorithmFileName = algorithmFileName.substring(algorithmFileName.lastIndexOf("/")+1, algorithmFileName.lastIndexOf("."));
        algorithmFileName = algorithmFileName+runnerableAlgorithm.getAlgorithmDetail().getPostfix();
		return algorithmFileName;
	}
	/**
	 * @param cmd
	 * @param tm
	 * @return
	 */
	private String genLegacyAlgorithmCmd(String cmd, String tm) {
		/**
		 * 如果是遗留算法
		 */
		
		cmd = tm+"\\"+tm+"\\"+cmd + " ";
//                Map<String,String> inputMap = paramXmlUriResult.getInputMap();
//                Map<String,String> outputMap = paramXmlUriResult.getOutputMap();
//                Map<String,String> paramMap = paramXmlUriResult.getParamMap();
		for(AlgorithmInput input:this.runnerableAlgorithm.getAlgorithmDetail().getAlgorithmInputs()){
//					Log4jInit.logger.info("input default:"+input.getNameDefault());
		    if(input.getNameDefault()){
		        cmd += this.runnerableAlgorithm.inputValues.get(input.getInputName()) + " ";

		    }else{
		        cmd += input.getInputName() + " " + this.runnerableAlgorithm.inputValues.get(input.getInputName()) + " ";
		    }
		}
		for(AlgorithmOutput output:this.runnerableAlgorithm.getAlgorithmDetail().getAlgorithmOutputs()){
		    if(output.getNameDefault()){
		        cmd += this.runnerableAlgorithm.outputValues.get(output.getOutputName()) + " ";
		    }else{
		        cmd += output.getOutputName() + " " + this.runnerableAlgorithm.outputValues.get(output.getOutputName()) + " ";
		    }
		}
		if(this.runnerableAlgorithm.paramValues!=null){
		    for(AlgorithmParam param:this.runnerableAlgorithm.getAlgorithmDetail().getAlgorithmParams()){
		    	
		    	if(param.getNameDefault()){
		            cmd += this.runnerableAlgorithm.paramValues.get(param.getParamSymbol()) + " ";
		        }else{
		            cmd += param.getParamSymbol() + " " + this.runnerableAlgorithm.paramValues.get(param.getParamSymbol()) + " ";
		        }
		    }
		}
		return cmd;
	}
	private String genMPICmd(String algorithmFileName, String cpuNum, String tm) {
		String cmd;
		if(cpuNum!=null && cpuNum!="" && cpuNum!="undefined"){
		    cmd = "mpiexec -n "+ cpuNum +" "+tm+"\\"+tm+"\\"+algorithmFileName;
		//	  cmd = "mpiexec -n "+ cpuNum +" "+algorithmFileName;
		}else{
		    cmd = tm+"\\"+tm+"\\"+ algorithmFileName;
		//    cmd =  algorithmFileName;
		}
		return cmd;
	}
	private String uploadJobXML(String paramXmlFileUri) {
		//paramXmlFileUri：是xml文件的本地路径
        //ftpFileUri：是要上传到服务器的路径
        String ftpFileUri = paramXmlFileUri.substring(paramXmlFileUri.lastIndexOf("/")+1);
        //2018-8-7在上传的xml文件上面一层加一个uuid的文件夹
        ftpFileUri = HttpConfig.ftpParamsUri+this.fatherTask.runningTaskBean.getTaskId()+"/"
                +this.runnerableAlgorithm.getAlgorithmDetail().getId()+"/"
                +UUID.randomUUID().toString().substring(0,5)+"/"+ftpFileUri;
        Log4jInit.logger.info("ftpFileUri:"+ftpFileUri);
        String upXmlResult = null;
        try {
//            upXmlResult = ftpuploadUtil.uploadFile(paramXmlFileUri,ftpFileUri);
           if(HttpConfig.copyFile){
        		upXmlResult = ftpuploadUtil.uploadFileByCopy(paramXmlFileUri,ftpFileUri);
        		Log4jInit.logger.info("========"+upXmlResult);
        		}else{
        		upXmlResult = ftpuploadUtil.uploadFile(paramXmlFileUri,ftpFileUri);
        			}
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(upXmlResult!=null && upXmlResult!="" && upXmlResult!="undefined"){
            this.fatherTask.updateState("完成分块："+(1)+"的参数XML文件上传");
          //  StaticUtil.deleteFile(paramXmlFileUri);
        }else{
            this.fatherTask.updateState("分块："+(1)+"的参数XML文件上传失败");
            return null;
        }
		return ftpFileUri;
	}
	private String analysisIniUri(List<String> list,String psn) {
		String targetFilePath = HttpConfig.scriptFileUri+"/";
        String iniFileUri = Thread.currentThread().getContextClassLoader().getResource("config.ini").getPath();
        String createIniFile = StaticUtil.createIniFile(this, algorithmHash,
                this.runnerableAlgorithm.getAlgorithmDetail().getName(), iniFileUri, targetFilePath,this.fatherTask.runningTaskBean.getTaskHash());
        String ftpIniFileUri = HttpConfig.ftpAlgorithmUri+"iniFileUri"+"/"
                +psn+"/"+createIniFile.substring(createIniFile.lastIndexOf("/")+1,createIniFile.length());
        try {
//        	ftpuploadUtil.uploadFile(createIniFile,ftpIniFileUri);
        	  if(HttpConfig.copyFile){
          		ftpuploadUtil.uploadFileByCopy(createIniFile,ftpIniFileUri);
          		}else{
          		ftpuploadUtil.uploadFile(createIniFile,ftpIniFileUri);
          			}
        } catch (IOException e) {
            e.printStackTrace();
            ftpIniFileUri = null;
        }
        if(ftpIniFileUri==null)
            return null;
        else
          //  list.add(createIniFile);
        	  list.add(ftpIniFileUri);  //传FTP路径的文件！！！
        return ftpIniFileUri;
	}


    private void insertState(String state, int blocksNum) {
		this.fatherTask.updateState(state);
		this.algorithmDao.insertHistoryAlgorithm(this.fatherTask.runningTaskBean.getTaskHash(),this.runnerableAlgorithm.getBlockId(),
				JSONObject.fromObject(this.runnerableAlgorithm).toString(), this.runnerableAlgorithm.getAlgorithmId(),
				blocksNum);
	}

	/**real
	 * for each map: produce one blocks' input and output map----oneBlock
	 * eg:key:block0_<input name>  value:{"blk":"c:\\CCJK\\test.bmp_867867","hosts":[{"hostName":"windows22"},{"hostName":"windows35"}]}
	 * @return
	 */
	private List<Map<String, PhysicalBlockInfor>> parseBlocksParams(){
		if(getInputBlocks()>0&&getOutputBlocks()>0){
			int numOfBlocks = this.inputBlocks.values().iterator().next().size();
			List<Map<String, PhysicalBlockInfor>> results = new ArrayList<>();
			for (int n = 0; n < numOfBlocks; n++) {
				/**
				 * produce one blocks' input and output map----oneBlock
				 * eg:key:block0_<input name>  value:{"blk":"c:\\CCJK\\test.bmp_867867","hosts":[{"hostName":"windows22"},{"hostName":"windows35"}]}
				 */
				Map<String, PhysicalBlockInfor> oneBlock = new HashMap<>();
				for (Entry<String, List<PhysicalBlockInfor>> one : this.inputBlocks.entrySet()) {
					oneBlock.put("block"+n+"_"+one.getKey(), one.getValue().get(n));
				}
				for (Entry<String, List<PhysicalBlockInfor>> one : this.outputBlocks.entrySet()) {
					oneBlock.put("block"+n+"_"+one.getKey(), one.getValue().get(n));
				}
				results.add(oneBlock);
			}
			/**
			 * 打印
			 */
//			for(Map<String, PhysicalBlockInfor> one:results){
//				for(Map.Entry<String, PhysicalBlockInfor> onee:one.entrySet()){
//					Log4jInit.logger.info("key:"+onee.getKey()+", value:"+onee.getValue().toString());
//				}
//			}
			return results;
		}else{
			return null;
		}
	}
	/**
	 * update job state
	 * @return
	 */
	public boolean updateJobFullState(String jobId, int times){
		HttpResultList result = null;
		try {
			result = AlgorithmOperator.getJobFullState(jobId, token);
		} catch (IOException e) {
			e.printStackTrace();
		}
		FullJobState fullJobState = (FullJobState)result.getDatas().get(0);
		if(fullJobState.getStatus().equals("DONE")||fullJobState.getStatus().equals("EXIT")){
			JobDao jonDao = new JobDao();
			if(jonDao.updateJobState(fullJobState.getStatus(),fullJobState.getJobName(),
					JSONObject.fromObject(fullJobState).toString(),this.fatherTask.runningTaskBean.getTaskHash(),this.algorithmHash,
					jobId)){
				this.checkJobState(fullJobState);
				return true;
			}else{
				return false;
			}
		}else if(times<30){
			Log4jInit.logger.info("times:"+times);
			return updateJobFullState(jobId,times+1);
		}else{
			return false;
		}

	}
	public boolean refreshJobFullState(String taskHash,String blockId,String jobId){
		/**
		 * 从服务器获取token
		 */
		HttpResult tokenResult = AlgorithmOperator.getToken(HttpConfig.userName, HttpConfig.passWord);
		if(tokenResult.isResult()){
			HttpResultList result = null;
			try {
				result = AlgorithmOperator.getJobFullState(jobId, tokenResult.getMessage());
			} catch (IOException e) {
				e.printStackTrace();
			}
			FullJobState fullJobState = (FullJobState)result.getDatas().get(0);
			JobDao jobDao = new JobDao();
			if(fullJobState.getStatus().equals("DONE")||fullJobState.getStatus().equals("EXIT")) {
				if(jobDao.updateJobState(fullJobState.getStatus(), fullJobState.getJobName(), JSONObject.fromObject(fullJobState).toString(),
						taskHash, blockId, jobId)){
					this.checkJobState(fullJobState);
					return true;
				}else {
					return false;
				}
			}else {
				return jobDao.updateRunningJobState(fullJobState.getStatus(), fullJobState.getJobName(), JSONObject.fromObject(fullJobState).toString(),
						taskHash, blockId, jobId);
			}
		}else{
			return false;
		}
	}

	public static boolean refreshJobFullState2(String taskHash,String blockId,String jobId){
		/**
		 * 从服务器获取token
		 */
		HttpResult tokenResult = AlgorithmOperator.getToken(HttpConfig.userName, HttpConfig.passWord);
		if(tokenResult.isResult()){
			HttpResultList result = null;
			try {
				result = AlgorithmOperator.getJobFullState(jobId, tokenResult.getMessage());
			} catch (IOException e) {
				e.printStackTrace();
			}
			FullJobState fullJobState = (FullJobState)result.getDatas().get(0);
			JobDao jobDao = new JobDao();
			Log4jInit.logger.info(fullJobState.getStatus());
			if(fullJobState.getStatus().equals("DONE")||fullJobState.getStatus().equals("EXIT")) {
				if(jobDao.updateJobState(fullJobState.getStatus(), fullJobState.getJobName(), JSONObject.fromObject(fullJobState).toString(),
						taskHash, blockId, jobId)){
				//	AlgorithmThread.checkJobState(fullJobState);
					return true;
				}else {
					return false;
				}
			}else {
				
				return jobDao.updateRunningJobState(fullJobState.getStatus(), fullJobState.getJobName(), JSONObject.fromObject(fullJobState).toString(),
						taskHash, blockId, jobId);
			}
		}else{
			return false;
		}
	}
	
	@SuppressWarnings("Duplicates")
	public void checkJobState(FullJobState fullJobState){
		this.jobState.put(fullJobState.getJobId(), fullJobState.getStatus());
		this.fullJobStates.add(fullJobState);
		boolean state = true;
		StringBuilder ids = new StringBuilder();
		for(Entry<String,String> map:this.jobState.entrySet()){
			state = state && (!map.getValue().equals("RUNNING"));
			ids.append(map.getKey() + " ");
		}
		if(state){ //finish
			this.algorithmDao.endRunningHistoryAlgorithmState(this.fatherTask.runningTaskBean.getTaskHash(),this.runnerableAlgorithm.getBlockId());
			this.fatherTask.updateStateFinish("算法运行完成！作业id为"+ids.toString()+",任务号："+this.fatherTask.runningTaskBean.getTaskHash(),true);
//			this.fatherTask.updateStatement(this.jobState);
			this.fatherTask.runningTaskBean.setNewestAlgorithm(this.algorithmHash);
			startNextAlgorithm();
		}
	}
	/**
	 * real
	 * @return -1:error in getting blocks
	 * 		   -2:the blocks of each input is not same
	 */
	private int getInputBlocks(){
//		Log4jInit.logger.info("input blocks");
		int numOfBlocks = -1;
		for(Entry<String, String> one:this.runnerableAlgorithm.inputValues.entrySet()){
			/**
			 * real
			 */
//			HttpResultList result = AlgorithmOperator.getBlocksByPathUri(,one.getValue());
			/**
			 * fake
			 */
//			Log4jInit.logger.info("input values:"+one.getKey()+":"+one.getValue());
			HttpResultList result = AlgorithmOperator.getBlocksByPathUri(4,one.getValue());
			//		HttpResultList result = AlgorithmOperator.getBlocksByPathUri(1,one.getValue());
			if(result.isResult()){
				List<PhysicalBlockInfor> blocks = new ArrayList<>();
				for(Object o:result.getDatas()){
					PhysicalBlockInfor oneBlock = (PhysicalBlockInfor)o;
					blocks.add(oneBlock);
				}
				inputBlocks.put(one.getKey(),blocks);
				/**
				 * the inputs' number of one algorithm should be same
				 */
				if(numOfBlocks==-1){
					numOfBlocks = blocks.size();
				}else{
					if(numOfBlocks!=blocks.size()){
						this.fatherTask.updateState("      错误！同一个算法下多个输入的物理地址块数量不一致");
						return -2;
					}
				}
			}else{
				this.fatherTask.updateState("      将算法输入逻辑地址解析为物理地址块出错");
				return -1;
			}
		}
//		Log4jInit.logger.info("inputBlocks.size():"+inputBlocks.size());
		return inputBlocks.size();

	}

	/**
	 * real
	 * @return -1:error in getting blocks
	 * 		   -2:the blocks of each output is not same
	 */
	private int getOutputBlocks(){
		int numOfBlocks = -1;
		for(Entry<String, String> one:this.runnerableAlgorithm.outputValues.entrySet()){
			/**
			 * real
			 */
//			HttpResultList result = AlgorithmOperator.getBlocksByPathUri(one.getValue());
			/**
			 * fake
			 */
//			Log4jInit.logger.info("output values:"+one.getKey()+":"+one.getValue());
			HttpResultList result = AlgorithmOperator.getBlocksByPathUri(4,one.getValue());
			if(result.isResult()){
				List<PhysicalBlockInfor> blocks = new ArrayList<>();
				for(Object o:result.getDatas()){
					PhysicalBlockInfor oneBlock = (PhysicalBlockInfor)o;
					blocks.add(oneBlock);
				}
				outputBlocks.put(one.getKey(),blocks);
				/**
				 * the outputs' number of one algorithm should be same
				 */
				if(numOfBlocks==-1){
					numOfBlocks = blocks.size();
				}else{
					if(numOfBlocks!=blocks.size()){
						this.fatherTask.updateState("      错误！同一个算法下多个输出的物理地址块数量不一致");
						return -2;
					}
				}
			}else{
				this.fatherTask.updateState("      将算法输出逻辑地址解析为物理地址块出错");
				return -1;
			}
		}
//		Log4jInit.logger.info("outputBlocks.size():"+outputBlocks.size());
		return outputBlocks.size();

	}
	private GenerateXmlUriResult generateParamsXml(XmlUtil xmlUtil, String executeAlgorithmFileName, Map<String, PhysicalBlockInfor> oneBlock, String blockPrefix){
		/**
		 * 封装参数xml文件
		 */
		GenerateXmlUriResult paramsXmlUri = null;
		try {
			//拼装执行所用的xml文件
			paramsXmlUri = xmlUtil.generateParamsXml(executeAlgorithmFileName, this.runnerableAlgorithm,oneBlock,blockPrefix);
			this.fatherTask.updateState("完成算法参数xml解析");
		} catch (IOException e) {
			e.printStackTrace();
			this.fatherTask.updateState("解析算法参数xml出错");
			return null;
		}
		return paramsXmlUri;
	}
	public boolean stopAlgorithm(){
		this.isStop = true;
		this.isTerminate = true;
		if(this.runningJobIds.size()>0) {
			//先停止，再记录到数据库
			HttpResult resultHttpResult =  AlgorithmOperator.stopJob(this.runningJobIds, this.token);
			//通过http接口停止返回的信息，记录
			this.fatherTask.updateState(resultHttpResult.getMessage());
			return resultHttpResult.isResult()&&this.doStop();
		}else{
			return true;
		}
	}

	public boolean pauseAlgorithm(){
		this.isPause = true;
		if(this.runningJobIds.size()>0) {
			HttpResult resultHttpResult =  AlgorithmOperator.pauseJob(this.runningJobIds, this.token);
			//通过http接口停止返回的信息，记录
			this.fatherTask.updateState(resultHttpResult.getMessage());
			return resultHttpResult.isResult()&&this.doPause();
		}else{
			return true;
		}
	}

	public boolean restartAlgorithm(){
		//2019.1.8添加result变量，但其实最后返回并没有用到
		boolean result = false;
		this.isPause = false;
		if(this.runningJobIds.size()>0) {
			HttpResult resultHttpResult =  AlgorithmOperator.restartJob(this.runningJobIds, this.token);
			//通过http接口停止返回的信息，记录
			this.fatherTask.updateState(resultHttpResult.getMessage());
			result =  resultHttpResult.isResult()&&this.doRestart();

		}else{
			result = true;
		}
		//2019.1.8添加在本地环境运行时，需要结束作业的操作
		int i =0;
		try {
			while(!isTerminate){
				i++;
				double a = 40*Math.random();
				int b = (int)(i%a);
				if((HttpConfig.fake)&&b==0){
					this.endOneJob();
				}
				else if(queryBasicTimes<this.runningJobIds.size() * 20){
					//				Log4jInit.logger.info(Thread.currentThread().getName());
					//				if(Thread.currentThread().isAlive())
					//				{
					//					Log4jInit.logger.info("huozhe");
					//				}
					//				if(!Thread.currentThread().isInterrupted())
					//				{
					//					Log4jInit.logger.info("is not interrupted");
					//				}
					if(Thread.currentThread().isInterrupted()){
						break;
					}
					Thread.sleep(1000);
				}
			}
		}
		//如果线程在sleep时，通过interrupt中断线程会抛出错误，因此将错误打印注释掉
		catch (InterruptedException e) {
//			e.printStackTrace();
		}
		return result;
	}

	public static void main(String[] args) {
		double a = 10*Math.random();
		int b = (int)(100%a);
	//	Log4jInit.logger.info(b);
	}
}